package cn.itcast.www.genericTest;

import java.io.PrintStream;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

import org.apache.commons.lang3.ArrayUtils;

public class ReflectionUtils {
	private final static PrintStream out = System.out;

	public static void printSuperclass(Type sup) {
		if (sup != null && !sup.equals(Object.class)) {
			out.print("extends ");
			printType(sup);
			out.println();
		}
	}

	public static void printInterfaces(Type[] impls) {
		if (impls != null && impls.length > 0) {
			out.print("implements ");
			int i = 0;
			for (Type impl : impls) {
				if (i++ > 0)
					out.print(",");
				printType(impl);
			}
			out.println();
		}
	}

	// 处理<T,E extends Number & serialize>这样的结构
	public static void printTypeParameters(TypeVariable<?>[] vars) {
		if (vars != null && vars.length > 0) {
			out.print("<");
			int i = 0;
			for (TypeVariable<?> var : vars) {
				if (i++ > 0)
					out.print(",");
				out.print(var.getName());
				printBounds(var.getBounds());
			}
			out.print(">");
		}
	}
    //处理extends List<Number> & serialize这样的结构
	public static void printBounds(Type[] bounds) {
		if (bounds != null && bounds.length > 0 && !(bounds.length == 1 && bounds[0] == Object.class)) {
			out.print(" extends ");
			int i = 0;
			for (Type bound : bounds) {
				if (i++ > 0)
					out.print("&");
				printType(bound);
			}
		}
	}
	//处理List<Number>这样的结构
	public static void printParams(Type[] types) {
		if (types != null && types.length > 0) {
			out.print("<");
			int i = 0;
			for (Type type : types) {
				if (i++ > 0)
					out.print(",");
				printType(type);
			}
			out.print(">");
		}
	}

	public static void printType(Type type) {
		// 该类型为不带类型参数的Class,如 ：java.util.ArrayList,而不是java.util.ArrayList<类型参数>
		if (type instanceof Class) {// 如<java.lang.Integer>
			Class<?> c = (Class) type;
			out.print(c.getName());
			// 该类型为带有参数的Class,如上：java.util.ArrayList<类型参数>
			// 此处的类型参数又可能是java.util.ArrayList<List<T,E extends Number>>
		} else if (type instanceof ParameterizedType) {
			ParameterizedType p = (ParameterizedType) type;
			Class c = (Class) p.getRawType(); // 原始类型为java.util.ArrayList
			Type o = p.getOwnerType();
			if (o != null) {
				printType(o);
				out.print(".");
			}
			out.print(c.getName());
			printParams(p.getActualTypeArguments()); // 类型参数为List<T,E extends
														// Number>
		} else if (type instanceof TypeVariable<?>) { // 类型变量为T或E等类型变量
			TypeVariable<?> v = (TypeVariable<?>) type;
			out.print(v.getName());
		} else if (type instanceof GenericArrayType) { // 类型变量为<T[]>或<E[]>等类型变量
			GenericArrayType a = (GenericArrayType) type;
			printType(a.getGenericComponentType());
			out.print("[]");
		} else if (type instanceof WildcardType) { // 类型变量为<? extends T> 或者<?
													// super E>
			WildcardType w = (WildcardType) type;
			Type[] upper = w.getUpperBounds();
			Type[] lower = w.getLowerBounds();
			if (upper.length == 1 && lower.length == 0) {
				out.print("? extends ");
				printType(upper[0]);
			} else if (upper.length == 0 && lower.length == 1) {
				out.print("? super ");
				printType(lower[0]);
			} else
				throw new AssertionError();
		}
	}
	
	//获取修饰符
	public static void printModifier(int modifier){
		if(Modifier.isAbstract(modifier)){
			out.print("abstract ");
		}else if(Modifier.isPrivate(modifier)){
			out.print("private ");
		}else if(Modifier.isPublic(modifier)){
			out.print("public ");
		}else if(Modifier.isProtected(modifier)){
			out.print("protected ");
		}
		if(Modifier.isStatic(modifier)){
			out.print("static ");
		}
		if(Modifier.isFinal(modifier)){
			out.print("final ");
		}
		
	}
	
	// 打印泛型类信息
	public static void printClass(Class c) {
		out.print("class ");
		// 打印类名
		out.print(c.getName());
		// 打印该类的类型参数
		printTypeParameters(c.getTypeParameters());
		out.println();
		// 打印父类
		printSuperclass(c.getGenericSuperclass());
		// 打印接口
		printInterfaces(c.getGenericInterfaces());
	}

	// 打印泛型方法信息
	public static void printMethod(Method m) {
		// 打印修饰符
		printModifier(m.getModifiers());
		// 打印泛型类型变量
		printTypeParameters(m.getTypeParameters());
		out.print(" ");
		// 打印返回值
		printType(m.getGenericReturnType());
		out.print(" ");
		// 打印方法名称
		out.print(m.getName() + " ");
		// 打印方法参数
		out.print("( ");
		Type[] types = m.getGenericParameterTypes();
		if (ArrayUtils.isNotEmpty(types)) {
			for (Type type : types) {
				printType(type);
			}
		}
		out.print(" ) ");
		// 打印异常
		types = m.getGenericExceptionTypes();
		if (ArrayUtils.isNotEmpty(types)) {
			out.print("throws ");
			for (Type type : types) {
				printType(type);
			}
		}
		// 打印左花括弧
		out.println("{}");

	}
	

	// class GenericClass<A, B extends Number & Serializable>
	public static void main(String[] args) throws ClassNotFoundException {
		String[] test = new String[] { "cn.itcast.www.genericTest.GenericClass" };
		GenericClass<String> gen = new GenericClass<String>(){};
		/*for (String name : test) {
			Class<?> c = Class.forName(name);
			printClass(c);
			out.println("{");
			Method[] methods = c.getDeclaredMethods();
			for (Method method : methods) {
				out.print("\t");
				printMethod(method);
			}
			out.println("}");
		}*/
		Class<?> c = gen.getClass();
		printClass(c);
		out.println("{");
		Method[] methods = c.getDeclaredMethods();
		for (Method method : methods) {
			out.print("\t");
			printMethod(method);
		}
		out.println("}");

	}
}
